#include <e.h>
#include "e_mod_main.h"
#include "e_mod_config.h"
#include "config.h"
#include "compiz.h"
#include "bang.h"
#include "bang_window.h"



# define D(x)  do {printf(__FILE__ ":%d:  ", __LINE__); printf x; fflush(stdout);} while (0)
//# define D(x)  ((void) 0)

/* module private routines */
static Bang * _bang_init(E_Module *m);
 
/* bang globals*/
REGION       emptyRegion;
REGION       infiniteRegion;
CompWindow  *lastFoundWindow = 0;
CompWindow  *lastDamagedWindow = 0;
int          defaultRefreshRate = 50;
Window       currentRoot = 0;
GLushort     defaultColor[4] = { 0xffff, 0xffff, 0xffff, 0xffff };

void
_berror(char *message)
{
   char buf[4096];
   
   /* Show in the console */
   snprintf(buf, sizeof(buf),"Unable to load Bang module:\n%s",message);
   e_error_message_show(buf);
   
   /* Create error dialog */
   if (!error_dialog)
   {
      /* Create error dialog */
      error_dialog = e_dialog_new(e_container_current_get(e_manager_current_get()),
                  "Bang", "_bang_error_dialog");
      if (!error_dialog) return;
      e_dialog_title_set(error_dialog, "Bang Module");
      e_dialog_button_add(error_dialog, "OK", NULL, NULL, NULL);
      e_dialog_text_set(error_dialog, "Hallo Dialog !!!");
      
      if (!error_dialog) return;
   }
   
   /* Show in dialog */
   snprintf(buf, sizeof(buf),"Unable to load Bang module:<br><br>%s<br><br>",message);
   e_dialog_text_set(error_dialog, buf);
   e_dialog_show(error_dialog);
}

/* public module routines. all modules must have these */
EAPI E_Module_Api e_modapi = {
   E_MODULE_API_VERSION,
   "Bang"
};

EAPI void *
e_modapi_init(E_Module *m)
{
   char buf[4096];

   //e_module_delayed_set(m, 0);
   
   error_dialog = NULL;
   
   bang = NULL;
   bang = _bang_init(m);
   if (!bang) return NULL;

   m->data = bang;
    
   
   snprintf(buf, sizeof(buf), "%s/e-module-bang.edj", e_module_dir_get(m));
   e_configure_registry_category_add("appearance", 10, "Appearance", NULL, "enlightenment/appearance");
   e_configure_registry_item_add("appearance/bang", 150, "Bang", NULL, buf, e_int_config_bang_module);
    
   
   /* WHY THIS?? IF NOT DELAYED MENU WINDOWS ARE BELOW OTHERS ????  WHY ????*/
   
   
   return bang;
}

EAPI int
e_modapi_shutdown(E_Module *m)
{
   e_configure_registry_item_del("appearance/bang");
   e_configure_registry_category_del("appearance");
   
   bang_composite_shoutdown(bang);
   
   
   if (bang)
   {
      printf("*\n");
      if (bang->config_dialog)
      {
         printf("**\n");
         e_object_del(E_OBJECT(bang->config_dialog));
         bang->config_dialog = NULL;
      }
      printf("***\n");
   }
   
    
   bang->module = NULL;
   free(bang->config);
   E_CONFIG_DD_FREE(bang->conf_edd);
   free(bang);
   printf("****\n");
   return 1;
}

EAPI int
e_modapi_save(E_Module *m)
{
   Bang *b;

   b = m->data;
   if (b)
      e_config_domain_save("module.bang", b->conf_edd, b->config);
   return 1;
}



static Bang *
_bang_init(E_Module *m)
{
   bang = NULL;
   bang = E_NEW(Bang, 1);
   if (!bang) return NULL;
    
   bang->module        = m;
   
   bang->config        = NULL;
   bang->conf_edd      = NULL;
   bang->config_dialog = NULL;
    
   bang->displays = NULL;
   bang->handlers = NULL;
   bang->plugins  = NULL;
   
   bang->shoutdown = 0;
   
   bang->programName = "elbang";
    
   bang->root = 0;
   bang->comp_screen = NULL;

   bang->conf_edd = E_CONFIG_DD_NEW("Bang_Config", Config);
#undef T
#undef D
#define T Config
#define D bang->conf_edd
   E_CONFIG_VAL(D, T, trans_border_only, UCHAR);
   E_CONFIG_VAL(D, T, trans_active_enable, UCHAR);
   E_CONFIG_VAL(D, T, trans_active_value, INT);
   E_CONFIG_VAL(D, T, trans_inactive_enable, UCHAR);
   E_CONFIG_VAL(D, T, trans_inactive_value, INT);
   E_CONFIG_VAL(D, T, trans_moving_enable, UCHAR);
   E_CONFIG_VAL(D, T, trans_moving_value, INT);
   E_CONFIG_VAL(D, T, trans_on_top_is_active, UCHAR);

   E_CONFIG_VAL(D, T, shadow_enable, UCHAR);
   E_CONFIG_VAL(D, T, shadow_dock_enable, UCHAR);
   E_CONFIG_VAL(D, T, shadow_active_size, INT);
   E_CONFIG_VAL(D, T, shadow_inactive_size,INT);
   E_CONFIG_VAL(D, T, shadow_opacity, DOUBLE);
   E_CONFIG_VAL(D, T, shadow_vert_offset, INT);
   E_CONFIG_VAL(D, T, shadow_horz_offset, INT);
   E_CONFIG_VAL(D, T, shadow_hide_on_move, UCHAR);
   E_CONFIG_VAL(D, T, shadow_hide_on_resize, UCHAR);

   E_CONFIG_VAL(D, T, fx_fade_enable, UCHAR);
   E_CONFIG_VAL(D, T, fx_fade_opacity_enable, UCHAR);
   E_CONFIG_VAL(D, T, fx_fade_in_step, DOUBLE);
   E_CONFIG_VAL(D, T, fx_fade_out_step, DOUBLE);

   bang->config = e_config_domain_load("module.bang", bang->conf_edd);

   if (!bang->config)
   {
      bang->config = E_NEW(Config, 1);

      bang->config->trans_border_only = 0;
      bang->config->trans_active_enable = 0;
      bang->config->trans_active_value = 100;
      bang->config->trans_inactive_enable = 1;
      bang->config->trans_inactive_value = 75;
      bang->config->trans_moving_enable = 1;
      bang->config->trans_moving_value = 50;
      bang->config->trans_on_top_is_active = 0;

      bang->config->shadow_enable = 1;
      bang->config->shadow_dock_enable = 1;
      bang->config->shadow_active_size = 7;
      bang->config->shadow_inactive_size = 4;
      bang->config->shadow_opacity = 0.85;
      bang->config->shadow_vert_offset = 3;
      bang->config->shadow_horz_offset = 3;
      bang->config->shadow_hide_on_move = 0;

      bang->config->fx_fade_enable = 1;
      bang->config->fx_fade_opacity_enable = 1;
      bang->config->fx_fade_in_step = 0.075;
      bang->config->fx_fade_out_step = 0.100;
   }

   E_CONFIG_LIMIT(bang->config->trans_active_value, 0, 100);
   E_CONFIG_LIMIT(bang->config->trans_inactive_value, 0, 100);
   E_CONFIG_LIMIT(bang->config->trans_moving_value, 0, 100);

   E_CONFIG_LIMIT(bang->config->shadow_active_size, 0, 50);
   E_CONFIG_LIMIT(bang->config->shadow_inactive_size, 0, 50);
   E_CONFIG_LIMIT(bang->config->shadow_opacity, 0.0, 1.0);
   E_CONFIG_LIMIT(bang->config->shadow_vert_offset, 0, 100);
   E_CONFIG_LIMIT(bang->config->shadow_horz_offset, 0, 100);

   E_CONFIG_LIMIT(bang->config->fx_fade_in_step, 0.0, 1.0);
   E_CONFIG_LIMIT(bang->config->fx_fade_out_step, 0.0, 1.0);

    
   printf("***  BANG  ***\n");

    
   emptyRegion.rects = &emptyRegion.extents;
   emptyRegion.numRects = 0;
   emptyRegion.extents.x1 = 0;
   emptyRegion.extents.y1 = 0;
   emptyRegion.extents.x2 = 0;
   emptyRegion.extents.y2 = 0;
   emptyRegion.size = 0;

   infiniteRegion.rects = &infiniteRegion.extents;
   infiniteRegion.numRects = 1;
   infiniteRegion.extents.x1 = MINSHORT;
   infiniteRegion.extents.y1 = MINSHORT;
   infiniteRegion.extents.x2 = MAXSHORT;
   infiniteRegion.extents.y2 = MAXSHORT;
   
//~ #if DEBUG
   //~ E_Action *act = NULL;
   //~ act = e_action_add("bang_debug");
   //~ if (act)
   //~ {
      //~ act->func.go_key = _debug_key_cb;
      //~ e_action_predef_name_set("Bang", "Debug data on console",
                                 //~ "bang_debug", NULL, NULL, 0);
   //~ }
//~ #endif 
    
   /* Create compiz display */
   if (!addDisplay())
      return NULL;
   
   /* load all the plugins found in dir */
   char buf[4096];
   snprintf(buf, sizeof(buf),"%s/plugins", e_module_dir_get(m));
   if (ecore_file_can_read(buf))
      loadPlugins(buf);
   
   /* ecore_events and addScreen() */
   if (!bang_composite_init(bang)) 
      return NULL;
   

   return bang;
}


